package net.tarine.gastronomi.client.tables;

import java.util.List;

import net.tarine.gastronomi.shared.AppConst;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;

public abstract class PagingTable<T> extends VerticalPanel {

	private int page = 0;
	
	private DataModel<T> model;
	private FlexTable table;
	private ButtonPanel lowerPanel;
	
	public PagingTable(DataModel<T> model) {
		this.model=model;
		table = new FlexTable();
		table.setStyleName("list-table");
		this.add(table);
		//this.add(lowerPanel); ora è nella tabella
	}
		
	public FlexTable getInnerTable() {
		return table;
	}
	
	public final void goPreviousPage() {
		if (page > 0) {
			page--;
			drawPage(page);
		}
	}
	
	public final void goNextPage() {
		page++;
		drawPage(page);
	}
	
	public void setTableRows(List<T> list) {
		lowerPanel = new ButtonPanel(page);
		getInnerTable().removeAllRows();
		boolean empty = (list == null);
		if (!empty) empty = (list.size() == 0);
		if (empty) {
			getInnerTable().clear();
			getInnerTable().setHTML(0, 0, "Nessun risultato");
			hideButtons();
		} else {
			//Fill with data
			addHeader();
			for (int i = 0; i<list.size(); i++) {
				addTableRow(i+1, list.get(i));
			}
			if (list.size() < AppConst.PAGING_ROWS) {
				lowerPanel.switchNextButton(false);
			} else {
				lowerPanel.switchNextButton(true);
			}
			getInnerTable().setWidget(list.size()+1, 0, lowerPanel);
			getInnerTable().getFlexCellFormatter().setColSpan(list.size()+1, 0, getInnerTable().getCellCount(0));
			getInnerTable().getFlexCellFormatter().setStyleName(list.size()+1, 0, "center-panel");
			showButtons();
			applyDataRowStyles();
		}
	}

	protected abstract void drawPage(int page);
	
	protected abstract void addHeader();
	
	protected abstract void addTableRow(int rowNum, T rowObj);

	public DataModel<T> getModel() {
		return model;
	}

	public void setModel(DataModel<T> model) {
		this.model=model;
		page = 0;
		drawPage(page);
	}
	
	private void applyDataRowStyles() {
		HTMLTable.RowFormatter rf = table.getRowFormatter();

		rf.addStyleName(0, "list-row-top");
		for (int row = 1; row < table.getRowCount()-1; ++row) {
			if ((row % 2) != 0) {
				rf.addStyleName(row, "list-row-odd");
			} else {
				rf.addStyleName(row, "list-row-even");
			}
		}
		rf.addStyleName(table.getRowCount()-1, "list-row-bot");
	}

	public void hideButtons() {
		lowerPanel.setVisible(false);
	}
	public void showButtons() {
		lowerPanel.setVisible(true);
	}
	
	//Inner classes
	
	
	private class ButtonPanel extends FlexTable {
		private static final String PREV = "<< precedenti ";
		private static final String NEXT = " successivi >>";
		private boolean prev = false;
		private boolean next = false;
		private Label prevLabel;
		private Label nextLabel;
		private Anchor prevButton;
		private Anchor nextButton;
		private int page;
		
		public ButtonPanel(int page) {
			this.page=page;
			prevLabel = new Label(PREV);
			prevButton = new Anchor(PREV);
			prevButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent arg0) {
					goPreviousPage();
				}
			});
			this.setWidget(0, 0, prevLabel);
			this.setWidget(0, 1, prevButton);
			nextLabel = new Label(NEXT);
			nextButton = new Anchor(NEXT);
			nextButton.addClickHandler(new ClickHandler() {
				@Override
				public void onClick(ClickEvent arg0) {
					goNextPage();
				}
			});
			this.setWidget(0, 2, nextLabel);
			this.setWidget(0, 3, nextButton);
			refreshPrevButton();
		}
		
		private void refreshPrevButton() {
			boolean isFirstPage = (page == 0);
			prev = !isFirstPage;
			verifyPanel();
		}
		private void switchNextButton(boolean isClickable) {
			next = isClickable;
			verifyPanel();
		}
		private void verifyPanel() {
			boolean panelVisible = prev || next;
			prevLabel.setVisible(!prev && panelVisible);
			prevButton.setVisible(prev && panelVisible);
			nextLabel.setVisible(!next && panelVisible);
			nextButton.setVisible(next && panelVisible);
		}
	}
}
